package com.suning.sawp.service.impl.bi;

import java.math.BigDecimal;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.annotation.Resource;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import com.google.common.collect.Maps;
import com.suning.framework.dal.client.DalClient;
import com.suning.sawp.constants.LoggerConstants;
import com.suning.sawp.dto.bi.OmsOrderItemPos;
import com.suning.sawp.dto.bi.StoreManRealIncSum;
import com.suning.sawp.intf.bi.BiDataDaoService;
import com.suning.sawp.intf.bi.BiDataTableRouteService;
import com.suning.sawp.po.bi.BiStoreRealIncDetailMEntity;
import com.suning.sawp.po.bi.StoreManDevMemberDetail;
import com.suning.sawp.po.bi.StoreManThisMonIncomeDetail;
import com.suning.sawp.po.bi.StoreManTotalDevMember;
import com.suning.sawp.po.bi.StoreManTotalIncome;
import com.suning.sawp.service.util.DateUtils;

@Service("biDataDaoService")
public class BiDataDaoServiceImpl implements BiDataDaoService {

    private static final Logger LOGGER = LoggerFactory.getLogger(LoggerConstants.SAWP_BI);

    /**
     * 工号，8位数字，正则表达式
     */
    private static final Pattern STAFF_ID_PATTERN = Pattern.compile("^\\d{8}$");

    /**
     * yyyyMMdd，正则表达式
     */
    private static final Pattern YYYYMMDD_PATTERN = Pattern.compile("\\d{4}\\d{2}\\d{2}");

    private static final String POS_CHANNEL = "pos";
    
    @Resource
    DalClient dalClient;

    @Resource
    BiDataTableRouteService biDataTableRouteService;

    @Override
    public StoreManTotalIncome queryTotalIncomeBySatffIdAndDate(String staffId, String date, String incSourceCode,
            boolean isBack) {
        Map<String, Object> paramMap = new HashMap<String, Object>();
        paramMap.put("employeeCd", staffId);
        paramMap.put("statisDate", date);
        if (StringUtils.isNotBlank(incSourceCode)) {
            paramMap.put("incSourceCode", incSourceCode);
        }
        chooseTable(paramMap);
        StoreManTotalIncome totalIncome = dalClient.queryForObject("STORE_TOT_INC_D.QUERY_INCOME_BY_DAY", paramMap,
                StoreManTotalIncome.class);
        // 因为数据是每天全量刷新,故昨日数据没有时，说明任务没有执行完，可以先取前一天的数据
        // isBack是否需要取前一天数据
        if (null == totalIncome || StringUtils.isBlank(totalIncome.getStatisDate()) && isBack) {
            paramMap.put("statisDate", DateUtils.getNextDay(date, -1, DateUtils.YYYYMMDD_PATTERN));
            chooseTable(paramMap);
            totalIncome = dalClient.queryForObject("STORE_TOT_INC_D.QUERY_INCOME_BY_DAY", paramMap,
                    StoreManTotalIncome.class);
        }
        return totalIncome;
    }

    @Override
    public StoreManTotalIncome queryTotalIncomeBySatffIdAndDate(String staffId, String date) {
        StoreManTotalIncome totalIncome = null;
        // 校验入参是否合法
        if (!validParams(staffId, date)) {
            LOGGER.warn("参数不合法，staffId：{}, date：{}", staffId, date);
        } else {
            Map<String, Object> paramMap = new HashMap<String, Object>();
            paramMap.put("employeeCd", staffId);
            paramMap.put("statisDate", date);
            chooseTable(paramMap);
            try {
                totalIncome = dalClient.queryForObject("STORE_TOT_INC_D.QUERY_INCOME_BY_DAY", paramMap,
                        StoreManTotalIncome.class);

                // 因为数据是每天全量刷新,故昨日数据没有时，说明任务没有执行完，可以先取前一天的数据
                if (null == totalIncome) {
                    paramMap.put("statisDate", DateUtils.getNextDay(date, -1, DateUtils.YYYYMMDD_PATTERN));
                    chooseTable(paramMap);
                    totalIncome = dalClient.queryForObject("STORE_TOT_INC_D.QUERY_INCOME_BY_DAY", paramMap,
                            StoreManTotalIncome.class);
                }
            } catch (Exception e) {
                LOGGER.error("STORE_TOT_INC_D.QUERY_INCOME_BY_DAY查询DB失败，入参：{}", paramMap.toString(), e);
            }
        }

        return totalIncome;
    }

    /**
     * 
     * 功能描述: 校验入参是否合法<br>
     * 〈功能详细描述〉 工号是否为8位数字，查询日期是否为yyyyMMdd格式
     * 
     * @param staffId
     * @param queryDate
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    private boolean validParams(String staffId, String queryDate) {
        Matcher staffIdMatcher = STAFF_ID_PATTERN.matcher(staffId);
        Matcher queryDateMatcher = YYYYMMDD_PATTERN.matcher(queryDate);

        return staffIdMatcher.matches() && queryDateMatcher.matches();
    }

    @Override
    public StoreManTotalDevMember queryTotalMemberByStaffIdAndDate(String staffId, String date) {
        Map<String, Object> paramMap = new HashMap<String, Object>();
        paramMap.put("employeeCode", staffId);
        paramMap.put("statisDate", date);
        chooseTable(paramMap);
        StoreManTotalDevMember totalIncome = dalClient.queryForObject("STORE_TOT_MEMBER_D.QUERY_MEMBER_POS_BY_DAY",
                paramMap, StoreManTotalDevMember.class);
        return totalIncome;
    }

    /**
     * 
     * 功能描述: 根据统计日期选择具体的分表<br>
     * 〈功能详细描述〉
     *
     * @param paramMap
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    private void chooseTable(Map<String, Object> paramMap) {
        // 选择统计数据的日期
        String statisDate = (String) paramMap.get("statisDate");
        // 走重跑数据表标志默认为否
        boolean goRewrite = false;
        if (null != paramMap.get("goRewrite")) {
            // 如果有走重跑数据表的标志
            goRewrite = (Boolean) paramMap.get("goRewrite");
        }
        String index = biDataTableRouteService.optReadGetTableIndex(statisDate, goRewrite);
        if (StringUtils.isNotBlank(index)) {
            // 获得有效的表编号
            paramMap.put("tableIndex", index);
        }
    }

    @Override
    public List<StoreManThisMonIncomeDetail> queryOmsOrderInMon(String staffId, String statisDate,
            String incSourceBiCode, int startIndex, int limit) {
        Map<String, Object> paramMap = new HashMap<String, Object>();
        paramMap.put("employeeCode", staffId);
        paramMap.put("statisDate", statisDate);
        paramMap.put("incSourceBiCode", incSourceBiCode);
        String monthFisrtDateStr = statisDate + "01";
        Date monthFisrtDate = DateUtils.getDateByStr(monthFisrtDateStr, DateUtils.YYYYMMDD_PATTERN);
        Calendar cal = Calendar.getInstance();
        cal.setTime(monthFisrtDate);
        // 月初时间
        cal.set(Calendar.DAY_OF_MONTH, 1);
        Date startTime = cal.getTime();
        // 月末时间
        cal.add(Calendar.MONTH, 1);
        cal.set(Calendar.DAY_OF_MONTH, 1);
        Date endTime = cal.getTime();
        paramMap.put("startTime", startTime);
        paramMap.put("endTime", endTime);
        paramMap.put("startIndex", startIndex);
        paramMap.put("limit", limit);
        // 会走重跑数据表
        paramMap.put("goRewrite", true);
        chooseTable(paramMap);

        List<StoreManThisMonIncomeDetail> omsOrders = dalClient.queryForList("STORE_AC_INC_DETAIL_D.QUERY_OMS_ORDERS",
                paramMap, StoreManThisMonIncomeDetail.class);
        return omsOrders;
    }

    @Override
    public List<OmsOrderItemPos> queryOmsOrderItems(List<String> omsOrderIds, String statisDate) {
        Map<String, Object> paramMap = new HashMap<String, Object>();
        paramMap.put("omsOrderIds", omsOrderIds);
        paramMap.put("statisDate", statisDate);
        // 会走重跑数据表
        paramMap.put("goRewrite", true);
        chooseTable(paramMap);

        List<OmsOrderItemPos> omsOrderItems = dalClient.queryForList("STORE_AC_INC_DETAIL_D.QUERY_OMS_ORDER_ITEMS",
                paramMap, OmsOrderItemPos.class);
        return omsOrderItems;
    }

    @Override
    public int countOmsOrderInMon(String staffId, String statisDate, String incSourceBiCode) {
        Map<String, Object> paramMap = new HashMap<String, Object>();
        paramMap.put("employeeCode", staffId);
        paramMap.put("incSourceBiCode", incSourceBiCode);
        paramMap.put("statisDate", statisDate);
        String monthFisrtDateStr = statisDate + "01";
        Date monthFisrtDate = DateUtils.getDateByStr(monthFisrtDateStr, DateUtils.YYYYMMDD_PATTERN);
        Calendar cal = Calendar.getInstance();
        cal.setTime(monthFisrtDate);
        // 月初时间
        cal.set(Calendar.DAY_OF_MONTH, 1);
        Date startTime = cal.getTime();
        // 月末时间
        cal.add(Calendar.MONTH, 1);
        cal.set(Calendar.DAY_OF_MONTH, 1);
        Date endTime = cal.getTime();
        paramMap.put("startTime", startTime);
        paramMap.put("endTime", endTime);
        // 会走重跑数据表
        paramMap.put("goRewrite", true);
        chooseTable(paramMap);

        Integer totalSize = dalClient.queryForObject("STORE_AC_INC_DETAIL_D.QUERY_OMS_ORDER_COUNT", paramMap,
                Integer.class);

        return totalSize == null ? 0 : totalSize;
    }

    @Override
    public double countTotalIncomeInMon(String staffId, String statisDate, String incSourceBiCode) {
        Map<String, Object> paramMap = new HashMap<String, Object>();
        paramMap.put("employeeCode", staffId);
        paramMap.put("incSourceBiCode", incSourceBiCode);
        paramMap.put("statisDate", statisDate);
        String monthFisrtDateStr = statisDate + "01";
        Date monthFisrtDate = DateUtils.getDateByStr(monthFisrtDateStr, DateUtils.YYYYMMDD_PATTERN);
        Calendar cal = Calendar.getInstance();
        cal.setTime(monthFisrtDate);
        // 月初时间
        cal.set(Calendar.DAY_OF_MONTH, 1);
        Date startTime = cal.getTime();
        // 月末时间
        cal.add(Calendar.MONTH, 1);
        cal.set(Calendar.DAY_OF_MONTH, 1);
        Date endTime = cal.getTime();
        paramMap.put("startTime", startTime);
        paramMap.put("endTime", endTime);
        // 会走重跑数据表
        paramMap.put("goRewrite", true);
        chooseTable(paramMap);

        Double totalIncome = dalClient.queryForObject("STORE_AC_INC_DETAIL_D.QUERY_PARTNUMBER_AMT_COUNT", paramMap,
                Double.class);
        return totalIncome;
    }

    @Override
    public List<StoreManThisMonIncomeDetail> queryIncomeDetailPage(String employeeId, String timeType, String sourceId,
            int startIndex, int pageSize) {

        Map<String, Object> paramMap = new HashMap<String, Object>();
        paramMap.put("employeeCode", employeeId);

        // 转换提成时间
        String queryDate = null;
        if ("0".equals(timeType)) { // 昨日提成
            queryDate = DateUtils.getNextDayStr(-1, DateUtils.YYYYMMDD_PATTERN);
            paramMap.put("yesterday", queryDate);
            paramMap.put("statisDate", queryDate);
        } else if ("2".equals(timeType)) { // 上月提成
            queryDate = DateUtils.getLastMonth();
            paramMap.put("lastMonth", queryDate);
            paramMap.put("statisDate", queryDate + "01"); // 月初
        } else { // 默认本月提成
            queryDate = DateUtils.getThisMonth();
            paramMap.put("thisMonth", DateUtils.getThisMonth());
            paramMap.put("statisDate", queryDate + "01"); // 月初
        }

        // 收入来源,默认全部来源
        if (null != sourceId && !"".equals(sourceId)) {
            paramMap.put("incSourceCode", sourceId);
        }

        // 起始位置 , 一页显示大小
        paramMap.put("startIndex", startIndex);
        paramMap.put("limit", pageSize);
        // 会走重跑数据表
        paramMap.put("goRewrite", true);
        chooseTable(paramMap);

        List<StoreManThisMonIncomeDetail> omsOrders = dalClient
                .queryForList("STORE_AC_INC_DETAIL_D.QUERY_INCOME_DETAIL", paramMap, StoreManThisMonIncomeDetail.class);
        return omsOrders;
    }

    @Override
    public List<OmsOrderItemPos> queryOmsOrderItems(String staffId, String statisDate, String incSourceBiCode,
            int startIndex, int limit) {

        Map<String, Object> paramMap = new HashMap<String, Object>();
        paramMap.put("employeeCode", staffId);
        paramMap.put("statisDate", statisDate);
        paramMap.put("incSourceBiCode", incSourceBiCode);
        String monthFisrtDateStr = statisDate + "01";
        Date monthFisrtDate = DateUtils.getDateByStr(monthFisrtDateStr, DateUtils.YYYYMMDD_PATTERN);
        Calendar cal = Calendar.getInstance();
        cal.setTime(monthFisrtDate);
        // 月初时间
        cal.set(Calendar.DAY_OF_MONTH, 1);
        Date startTime = cal.getTime();
        // 月末时间
        cal.add(Calendar.MONTH, 1);
        cal.set(Calendar.DAY_OF_MONTH, 1);
        Date endTime = cal.getTime();
        paramMap.put("startTime", startTime);
        paramMap.put("endTime", endTime);
        paramMap.put("startIndex", startIndex);
        paramMap.put("limit", limit);
        // 会走重跑数据表
        paramMap.put("goRewrite", true);
        chooseTable(paramMap);

        List<OmsOrderItemPos> omsOrderItems = dalClient.queryForList("STORE_AC_INC_DETAIL_D.QUERY_OMS_ORDER_ITEMS_PAGE",
                paramMap, OmsOrderItemPos.class);
        return omsOrderItems;
    }

    @Override
    public String getMaxStaticDate(String timeType) {
        Map<String, Object> paramMap = new HashMap<String, Object>();

        if ("2".equals(timeType)) { // 上月提成
            paramMap.put("statisDate", DateUtils.getLastMonth());
        } else { // 默认本月提成
            paramMap.put("statisDate", DateUtils.getThisMonth());
        }
        // 会走重跑数据表
        paramMap.put("goRewrite", true);
        chooseTable(paramMap);
        Date maxOrderTime = dalClient.queryForObject("STORE_AC_INC_DETAIL_D.GET_OMS_ORDER_MAX_STATIC_DATE", paramMap,
                Date.class);
        // 如果本月,或则上月数据为空,往前一个月取统计时间
        if (null == maxOrderTime) {
            paramMap.put("statisDate",
                    DateUtils.getLastMonth(String.valueOf(paramMap.get("statisDate")), DateUtils.YYYYMM_PATTERN));
            chooseTable(paramMap);
            maxOrderTime = dalClient.queryForObject("STORE_AC_INC_DETAIL_D.GET_OMS_ORDER_MAX_STATIC_DATE", paramMap,
                    Date.class);
        }
        String statisDate = DateUtils.getDateStrByFormat(maxOrderTime, DateUtils.YYYYMMDD_PATTERN);
        return statisDate;
    }

    @Override
    public BigDecimal getStoreManMainPushActAmount(String staffId, Date startTime,
            Date endTime, Set<String> goodsCodes) {
        if (CollectionUtils.isEmpty(goodsCodes)) {
            return new BigDecimal("0.00");
        }
        Map<String, Object> paramMap = new HashMap<String, Object>();
        paramMap.put("employeeCode", staffId);
        paramMap.put("startTime", startTime);
        paramMap.put("endTime", endTime);
        paramMap.put("incSourceBiCode", "POS");
        paramMap.put("goodsCodes", goodsCodes);
        paramMap.put("goRewrite", true);
        paramMap.put("statisDate", DateUtils.getThisMonth());
        chooseTable(paramMap);
        BigDecimal actAmount = dalClient.queryForObject(
                "STORE_AC_INC_DETAIL_D.QUERY_STORE_MAN_ACT_MAIN_PUSH", paramMap, BigDecimal.class);
        
        return actAmount;
    }

    @Override
    public List<OmsOrderItemPos> queryItemIncomeDetailByOrderNo(String omsOrderNo, String date) {
        Map<String, Object> paramMap = Maps.newHashMap();
        paramMap.put("omsOrderId", omsOrderNo);
        paramMap.put("statisDate", date);
        paramMap.put("goRewrite", true);
        chooseTable(paramMap);
        return dalClient.queryForList("STORE_AC_INC_DETAIL_D.QUERY_OMS_ORDER_ITEMS_COMMISSION", paramMap,
                OmsOrderItemPos.class);
    }

    @Override
    public int countLastMonMember(String staffId) {
        // 上月月头日期
        Date lastMonStartDate = DateUtils.getFirstDayZeroPointOfMonth(-1);
        String lastMonStartDateStr = DateUtils.getDateStrByFormat(
                lastMonStartDate, DateUtils.YYYYMMDD_PATTERN);
        // 当月月头日期
        Date thisMonStartDate = DateUtils.getFirstDayZeroPointOfMonth(0);
        String thisMonStartDateStr = DateUtils.getDateStrByFormat(
                thisMonStartDate, DateUtils.YYYYMMDD_PATTERN);
        return countMemberInPriord(staffId, lastMonStartDateStr, thisMonStartDateStr);
    }

    @Override
    public int countMemberInPriord(String staffId, String startDate, String endDate) {
        Map<String, Object> paramMap = new HashMap<String, Object>();
        paramMap.put("staffId", staffId);
        paramMap.put("startDate", startDate);
        paramMap.put("endDate", endDate);
        paramMap.put("sourceCode", POS_CHANNEL);
        Integer count = dalClient.queryForObject(
                "STORE_REG_MEMBER_DETAIL_D.COUNT_MEMBER_TIME_PERIOD", paramMap, Integer.class);
        return null != count ? count : 0;
    }

    @Override
    public List<StoreManDevMemberDetail> queryMemberDetailList(String staffId, String startDate, 
            String endDate, int startIndex, int limit) {
        Map<String, Object> paramMap = new HashMap<String, Object>();
        paramMap.put("staffId", staffId);
        paramMap.put("startDate", startDate);
        paramMap.put("endDate", endDate);
        paramMap.put("sourceCode", POS_CHANNEL);
        paramMap.put("startIndex", startIndex);
        paramMap.put("limit", limit);
        List<StoreManDevMemberDetail> list = dalClient.queryForList("STORE_REG_MEMBER_DETAIL_D.QUERY_MEMBER_DETAILS"
                , paramMap, StoreManDevMemberDetail.class);
                
        return list;
    }

    @Override
    public StoreManRealIncSum queryTotalIncomeInfo(String staffId) {
        Map<String, Object> paramMap = new HashMap<String, Object>();
        paramMap.put("staffId", staffId);
        StoreManRealIncSum detailMEntity = 
                dalClient.queryForObject("biStoreRealIncDetailM.QUERY_TOTAL_INCOME"
                        , paramMap, StoreManRealIncSum.class);
        return detailMEntity;
    }

    @Override
    public List<BiStoreRealIncDetailMEntity> queryRealIncomeDetails(String staffId, int startIndex, int limit) {
        Map<String, Object> paramMap = new HashMap<String, Object>();
        paramMap.put("staffId", staffId);
        paramMap.put("startIndex", startIndex);
        paramMap.put("limit", limit);
        List<BiStoreRealIncDetailMEntity> list = dalClient.queryForList(
                "biStoreRealIncDetailM.QUERY_INCOME_DETAIL", paramMap, BiStoreRealIncDetailMEntity.class);
        return list;
    }

    @Override
    public int countPosMember() {
        Integer count = dalClient.queryForObject("STORE_REG_MEMBER_DETAIL_D.COUNT_TOTAL_SIZE", null, Integer.class);
        return null != count ? count : 0;
    }

    @Override
    public List<StoreManDevMemberDetail> queryPosMemberByPage(int startIndex, int limit) {
        Map<String, Object> paramMap = new HashMap<String, Object>();
        paramMap.put("startIndex", startIndex);
        paramMap.put("limit", limit);
        return dalClient.queryForList("STORE_REG_MEMBER_DETAIL_D.QUERY_RECORDS_PAGE", paramMap, StoreManDevMemberDetail.class);
    }
     
}
